if ( p->net_vif_list[i] == NULL ) continue;
virt_startinfo_addr->net_rings[i] =
virt_to_phys(p->net_vif_list[i]->shared_rings);
+ memcpy(virt_startinfo_addr->net_vmac[i],
+ p->net_vif_list[i]->vmac, ETH_ALEN);
}
/* Add block io interface */
if ( p->net_vif_list[i] == NULL ) continue;
virt_startinfo_address->net_rings[i] =
virt_to_phys(p->net_vif_list[i]->shared_rings);
+ memcpy(virt_startinfo_address->net_vmac[i],
+ p->net_vif_list[i]->vmac, ETH_ALEN);
}
/* Add block io interface */
/* XXX SMH: below is rather vile; pulled in to allow network console */
extern int netif_rx(struct sk_buff *);
-extern struct net_device *the_dev;
typedef struct my_udphdr {
__u16 source;
iph->id = 0xdead;
iph->ttl = 255;
iph->protocol= 17;
- iph->daddr = htonl(0xa9fe0001); /* 169.254.0.1 */
- iph->saddr = htonl(0xa9fe0001); /* 169.254.0.1 */
+ iph->daddr = htonl(0xa9fe0100); /* 169.254.1.0 */
+ iph->saddr = htonl(0xa9fe0100); /* 169.254.1.0 */
iph->tot_len = htons(hdr_size + len);
iph->check = 0;
iph->check = compute_cksum((__u16 *)iph, sizeof(struct my_iphdr)/2);
spin_lock_init(&new_vif->rx_lock);
spin_lock_init(&new_vif->tx_lock);
+ /*
+ * Virtual MAC is a hash of the real physical MAC. Chosen so that the
+ * first vif of domain 0 gets the physical MAC address.
+ */
+ memcpy(new_vif->vmac, the_dev->dev_addr, ETH_ALEN);
+ ((unsigned short *)new_vif->vmac)[1] ^= htons(p->domain);
+ ((unsigned short *)new_vif->vmac)[2] ^= htons(dom_vif_idx);
+
p->net_vif_list[dom_vif_idx] = new_vif;
write_unlock_irqrestore(&tasklist_lock, flags);
void __init net_init (void)
{
- net_rule_t new_rule;
-
net_rule_list = NULL;
net_vif_cache = kmem_cache_create("net_vif_cache",
sizeof(net_vif_t),
net_rule_cache = kmem_cache_create("net_rule_cache",
sizeof(net_rule_ent_t),
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-
- /* Bootstrap outbound rule. */
- memset(&new_rule, 0, sizeof(net_rule_t));
- new_rule.src_vif = 0;
- new_rule.dst_vif = VIF_PHYSICAL_INTERFACE;
- new_rule.action = NETWORK_ACTION_ACCEPT;
- new_rule.proto = NETWORK_PROTO_ANY;
- add_net_rule(&new_rule);
-
- /* Bootstrap inbound rule. */
- memset(&new_rule, 0, sizeof(net_rule_t));
- new_rule.src_vif = VIF_ANY_INTERFACE;
- new_rule.dst_vif = 0;
- new_rule.action = NETWORK_ACTION_ACCEPT;
- new_rule.proto = NETWORK_PROTO_ANY;
- add_net_rule(&new_rule);
}
unsigned long mod_len; /* size (bytes) of pre-loaded module */
/* Machine address of net rings for each VIF. Will be page aligned. */
unsigned long net_rings[MAX_DOMAIN_VIFS];
+ unsigned char net_vmac[MAX_DOMAIN_VIFS][6];
/* Machine address of block-device ring. Will be page aligned. */
unsigned long blk_ring;
unsigned int dom_id;
#include <hypervisor-ifs/network.h>
+#include <xeno/if_ether.h>
+
+extern struct net_device *the_dev;
+
/*
* shadow ring structures are used to protect the descriptors from
* tampering after they have been passed to the hypervisor.
struct list_head list; /* scheduling list */
atomic_t refcnt;
spinlock_t rx_lock, tx_lock;
+ unsigned char vmac[ETH_ALEN];
} net_vif_t;
#define get_vif(_v) (atomic_inc(&(_v)->refcnt))
unsigned short size;
unsigned char offset, status = RING_STATUS_OK;
- memset(skb->mac.ethernet->h_dest, 0, ETH_ALEN);
+ memcpy(skb->mac.ethernet->h_dest, vif->vmac, ETH_ALEN);
if ( ntohs(skb->mac.ethernet->h_proto) == ETH_P_ARP )
- memset(skb->nh.raw + 18, 0, ETH_ALEN);
+ memcpy(skb->nh.raw + 18, vif->vmac, ETH_ALEN);
if ( (i = vif->rx_cons) == vif->rx_prod )
return;
add_to_net_schedule_list_tail(vif);
skb->destructor = tx_skb_release;
-
+
skb->head = skb->data = tx->header;
skb->end = skb->tail = skb->head + PKT_PROT_LEN;
{
case ETH_P_ARP:
if ( len < 42 ) break;
- memcpy(data + 22, dev->dev_addr, 6);
+ memcpy(data + 22, dev->dev_addr, ETH_ALEN);
return ETH_P_ARP;
case ETH_P_IP:
return ETH_P_IP;
(PGT_writeable_page | current->domain)) ||
(buf_page->tot_count != 1) )
{
- DPRINTK("Need a mapped-once writeable page (%d/%d/%08x)\n",
+ DPRINTK("Need a mapped-once writeable page (%ld/%ld/%08lx)\n",
buf_page->type_count, buf_page->tot_count, buf_page->flags);
make_rx_response(vif, rx.id, 0, RING_STATUS_BAD_PAGE, 0);
goto rx_unmap_and_continue;
(void)HYPERVISOR_network_op(&op);
/*
- * Xen creates a pair of bootstrap rules which allows domain 0 to
- * send and receive any packet. These rules can be removed once we
- * have configured an IP address.
+ * When the first real interface is brought up we delete the start-of-day
+ * bootstrap rules -- they were only installed to allow an initial DHCP
+ * request and response.
*/
if ( (idx == 0) && (event == NETDEV_UP) && !removed_bootstrap_rules )
{
op.cmd = NETWORK_OP_DELETERULE;
op.u.net_rule.proto = NETWORK_PROTO_ANY;
op.u.net_rule.action = NETWORK_ACTION_ACCEPT;
-
op.u.net_rule.src_vif = 0;
op.u.net_rule.dst_vif = VIF_PHYSICAL_INTERFACE;
(void)HYPERVISOR_network_op(&op);
-
op.u.net_rule.src_vif = VIF_ANY_INTERFACE;
op.u.net_rule.dst_vif = 0;
(void)HYPERVISOR_network_op(&op);
INIT_LIST_HEAD(&dev_list);
- /*
- * Domain 0 must poke its own network rules as it discovers its IP
- * addresses. All other domains have a privileged "parent" to do this
- * for them at start of day.
- */
if ( start_info.dom_id == 0 )
+ {
+ /*
+ * Domain 0 creates wildcard rules to allow DHCP to find its first IP
+ * address. These wildcard rules are deleted when the first inet
+ * interface is brought up.
+ */
+ network_op_t op;
+ memset(&op, 0, sizeof(op));
+ op.cmd = NETWORK_OP_ADDRULE;
+ op.u.net_rule.proto = NETWORK_PROTO_ANY;
+ op.u.net_rule.action = NETWORK_ACTION_ACCEPT;
+ op.u.net_rule.src_vif = 0;
+ op.u.net_rule.dst_vif = VIF_PHYSICAL_INTERFACE;
+ (void)HYPERVISOR_network_op(&op);
+ op.u.net_rule.src_vif = VIF_ANY_INTERFACE;
+ op.u.net_rule.dst_vif = 0;
+ (void)HYPERVISOR_network_op(&op);
+
+ /*
+ * Domain 0 must poke its own network rules as it discovers its IP
+ * addresses. All other domains have a privileged "parent" to do this
+ * for them at start of day.
+ */
(void)register_inetaddr_notifier(¬ifier_inetdev);
+ }
for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
{
dev->stop = network_close;
dev->get_stats = network_get_stats;
- memset(dev->dev_addr, 0, ETH_ALEN);
- *(unsigned int *)(dev->dev_addr + 1) = i;
+ memcpy(dev->dev_addr, start_info.net_vmac[i], ETH_ALEN);
if ( (err = register_netdev(dev)) != 0 )
{